/*
 * Copyright (c) 2009. Silenus Consultoria, S.L.
 */
package es.silenus.detecta.controller;

import es.silenus.detecta.Constants;

import es.silenus.detecta.dao.KnowledgeUnitDAO;
import es.silenus.detecta.dao.Page;
import es.silenus.detecta.dao.SurveyDAO;

import es.silenus.detecta.model.Question;
import es.silenus.detecta.model.Survey;
import es.silenus.detecta.model.User;

import org.apache.commons.lang.CharUtils;
import org.apache.commons.lang.StringUtils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;

import java.sql.Date;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * DOCUMENT ME!
 *
 * @author <a href="mailto:dgarcia@silenus-consultoria.es">Daniel García</a>
 *
 * @since 16-abr-2009 11:45:38
 */
public class SurveyController extends BaseController {
	/**
	 * Logger for this class.
	 */
	private static final Log LOG = LogFactory.getLog(SurveyController.class);

	/**
	 * Design lifecycle phase.
	 */
	public static final int DESIGN_LIFECYCLE = 1;

	/**
	 * The surveys DAO
	 */
	private SurveyDAO surveyDAO;

	/**
	 * The knowledge unit DAO.
	 */
	private KnowledgeUnitDAO knowledgeUnitDAO;

	/**
	 * Sets the survey DAO.
	 *
	 * @param surveyDAO the survey DAO.
	 */
	public void setSurveyDAO(final SurveyDAO surveyDAO) {
		this.surveyDAO = surveyDAO;
	}

	/**
	 * Sets the knowledge unit DAO.
	 *
	 * @param knowledgeUnitDAO the knowledge unit DAO.
	 */
	public void setKnowledgeUnitDAO(final KnowledgeUnitDAO knowledgeUnitDAO) {
		this.knowledgeUnitDAO = knowledgeUnitDAO;
	}

	/**
	 * Loads an existing survey.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String loadSurvey(HttpServletRequest request, HttpServletResponse response) {
		String id = request.getParameter("id");

		int surveyId = (id != null) ? Integer.parseInt(id) : 0;
		Survey survey = surveyDAO.findById(surveyId);

		request.setAttribute("survey", survey);

		return "secure/designer/survey";
	}

	/**
	 * Updates an existing survey or creates a new one.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 *
	 * @throws JSONException if something goes wrong.
	 */
	public String updateSurvey(HttpServletRequest request, HttpServletResponse response) throws JSONException {
		final User current = this.getUser(request);
		final int organizationId = current.getOrganization().getId();
		JSONObject jsonSurvey = new JSONObject(request.getParameter("survey"));

		String id = jsonSurvey.getString("id");

		int surveyId = (id != null) ? Integer.parseInt(id) : 0;

		Survey survey;

		if(surveyId > 0) {
			survey = surveyDAO.findById(surveyId);

			/*
			   // Check lifecycle
			   if (survey.getLifecycle().getId() > DESIGN_LIFECYCLE) {
			     request.setAttribute(Constants.ERRORS, "survey.invalid.lifecycle");
			     return "secure/designer/survey-update-error";
			   }
			 */
		} else {
			survey = new Survey();
		}

		// Check if code is changing
		String code = jsonSurvey.getString("code");
		Survey otherSurvey = surveyDAO.findByCode(code, organizationId);

		if((otherSurvey != null) && (otherSurvey.getId() != surveyId)) {
			request.setAttribute(Constants.ERRORS, "survey.code.duplicated");

			return "secure/designer/survey-update-error";
		}

		survey.setCode(code);
		survey.setOrganization(current.getOrganization());
		survey.setDescription(jsonSurvey.getString("description"));
		survey.setTitle(jsonSurvey.getString("title"));

		SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");

		Date theDate;

		try {
			theDate = new Date(format.parse(jsonSurvey.getString("startDate")).getTime());
			survey.setStartDate(new Date(theDate.getTime()));
		} catch(ParseException e) {
			LOG.error("Error parsing start date: " + jsonSurvey.getString("startDate"), e);
			survey.setStartDate(new Date(System.currentTimeMillis()));
		}

		try {
			theDate = new Date(format.parse(jsonSurvey.getString("endDate")).getTime());
			survey.setEndDate(new Date(theDate.getTime()));
		} catch(ParseException e) {
			LOG.error("Error parsing end date: " + jsonSurvey.getString("endDate"), e);
			survey.setStartDate(new Date(System.currentTimeMillis()));
		}

		try {
			theDate = new Date(format.parse(jsonSurvey.getString("archivedDate")).getTime());
			survey.setArchivedDate(new Date(theDate.getTime()));
		} catch(ParseException e) {
			LOG.error("Error parsing archived date: " + jsonSurvey.getString("archivedDate"), e);
			survey.setStartDate(new Date(System.currentTimeMillis()));
		}

		if(surveyId == 0) {
			surveyDAO.save(survey);
		}

		if(jsonSurvey.has("questions")) {
			// Remove before add
			survey.getQuestions().clear();
			surveyDAO.update(survey);

			JSONArray jsonQuestions = jsonSurvey.getJSONArray("questions");
			JSONObject jsonQuestion;
			Question tempQuestion;

			for(int i = 0; i < jsonQuestions.length(); ++i) {
				jsonQuestion = jsonQuestions.getJSONObject(i);

				tempQuestion = new Question();
				tempQuestion.setCode(jsonQuestion.getString("code"));
				tempQuestion.setDescription(jsonQuestion.getString("description"));
				tempQuestion.setUnit(knowledgeUnitDAO.findByCode(jsonQuestion.getString("unit"), organizationId));

				survey.add(tempQuestion);
			}
		}

		surveyDAO.update(survey);

		request.setAttribute("survey", survey);

		return "secure/designer/survey-updated";
	}

	/**
	 * Finds surveys by a given criteria.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String findSurvey(final HttpServletRequest request, final HttpServletResponse response) {
		final User current = getUser(request);

		Map<String, Object> sample = new HashMap<String, Object>();
		String temp = request.getParameter("id");

		if(temp != null) {
			sample.put("id", temp);
		}

		temp = request.getParameter("code");

		if(temp != null) {
			sample.put("code", temp);
		}

		temp = request.getParameter("title");

		if(temp != null) {
			sample.put("title", temp);
		}

		temp = request.getParameter("description");

		if(temp != null) {
			temp = StringUtils.replaceChars(temp, CharUtils.CR, ' ');
			temp = StringUtils.replaceChars(temp, CharUtils.LF, ' ');
			sample.put("description", temp);
		}

		temp = request.getParameter("lifecycle");

		if(temp != null) {
			sample.put("lifecycle.id", Integer.parseInt(temp));
		}

		sample.put("organization.id", current.getOrganization().getId());


		int start = Integer.parseInt(request.getParameter("start"));
		int limit = Integer.parseInt(request.getParameter("limit"));
		String[] sortFields = request.getParameterValues("sort");
		String[] sortDirections = request.getParameterValues("dir");

		Page<Survey> page = surveyDAO.findByExample(sample, start, limit, sortFields, sortDirections);

		request.setAttribute("page", page);

		return "secure/designer/surveys";
	}

	/**
	 * Copies a survey.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String copySurvey(final HttpServletRequest request, final HttpServletResponse response) {
		String id = request.getParameter("id");

		User user = getUser(request);

		int surveyId = (id != null) ? Integer.parseInt(id) : 0;
		Survey survey = surveyDAO.findById(surveyId);

		Survey cloneSurvey = new Survey();

		cloneSurvey.setCode("*" + survey.getCode());
		cloneSurvey.setTitle("*" + survey.getTitle());
		cloneSurvey.setDescription("*" + survey.getDescription());
		cloneSurvey.setOrganization(user.getOrganization());
		cloneSurvey.setStartDate(survey.getStartDate());
		cloneSurvey.setEndDate(survey.getEndDate());
		cloneSurvey.setArchivedDate(survey.getArchivedDate());

		Question cloneQuestion;

		for(Question question : survey.getQuestions()) {
			cloneQuestion = new Question();

			cloneQuestion.setCode(question.getCode());
			cloneQuestion.setDescription(question.getDescription());
			cloneQuestion.setUnit(question.getUnit());

			cloneSurvey.add(cloneQuestion);
		}

		request.setAttribute("survey", cloneSurvey);

		return "secure/designer/survey";
	}

	/**
	 * Checks remove surveys.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String checkDeleteSurveys(final HttpServletRequest request, final HttpServletResponse response) {
		String[] surveys = request.getParameterValues("elements");

		if(surveys != null) {
			Integer[] surveyIds = new Integer[surveys.length];

			for(int i = 0; i < surveys.length; ++i) {
				surveyIds[i] = Integer.parseInt(surveys[i]);
			}

			List theSurveys = surveyDAO.getRemovalInformation(surveyIds);

			request.setAttribute("surveys", theSurveys);
		}

		return "secure/designer/surveys-check-removed";
	}

	/**
	 * Remove surveys.
	 *
	 * @param request the request.
	 * @param response the response.
	 *
	 * @return the view name.
	 */
	public String deleteSurveys(final HttpServletRequest request, final HttpServletResponse response) {
		String[] surveys = request.getParameterValues("elements");

		if(surveys != null) {
			Integer[] surveyIds = new Integer[surveys.length];

			for(int i = 0; i < surveys.length; ++i) {
				surveyIds[i] = Integer.parseInt(surveys[i]);
			}

			surveyDAO.remove(surveyIds);
		}

		return "secure/designer/surveys-removed";
	}
}
